﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Xml;

namespace iNet.Media.Xmp
{
	#region ArrayXmpPropertyValue
	/// <summary>
	/// 陣列型別的 XMP Property 值。
	/// </summary>
	public class ArrayXmpPropertyValue : XmpPropertyValue
	{ 
		#region 欄位
		XmpArrayType _ArrayType;
		List<XmpPropertyValue> _Items = new List<XmpPropertyValue>();
		#endregion
		#region 建構子
		/// <summary>
		/// 初始化新的 ArrayXmpPropertyValue 執行個體。
		/// </summary>
		/// <param name="arrayType">陣列類型。</param>
		public ArrayXmpPropertyValue(XmpArrayType arrayType)
		{
			this.ArrayType = arrayType;
		}
		#endregion
		#region ArrayType
		/// <summary>
		/// 取得或設定陣列類型。
		/// </summary>
		public XmpArrayType ArrayType
		{
			get
			{
				return _ArrayType;
			}
			set
			{
				if (!Enum.IsDefined(typeof(XmpArrayType), value))
					throw new ArgumentException();
				_ArrayType = value;
			}
		}
		#endregion
		#region CloneCore
		/// <summary>
		/// 建立副本。
		/// </summary>
		/// <returns>ArrayXmpPropertyValue 副本。</returns>
		protected override XmpPropertyValue CloneCore()
		{
			ArrayXmpPropertyValue value = new ArrayXmpPropertyValue(_ArrayType);
			value._Items.AddRange(_Items);
			return value;
		}
		#endregion
		#region ExtractValue
		/// <summary>
		/// 取得此 XMP Property 值所代表的實際內容。
		/// </summary>
		/// <returns>XMP Property 值所代表的實際內容。</returns>
		public override object ExtractValue()
		{
			//轉成 MultiLanguageString
			List<string> languages = new List<string>();
			if (this.IsLanguageAlternative(languages))
			{
				MultiLanguageString mlString = new MultiLanguageString();
				bool error = false;
				for (int i = 0; i < _Items.Count; ++i)
				{
					TextXmpPropertyValue textValue = _Items[i] as TextXmpPropertyValue;
					if (textValue != null)
					{
						if (languages[i] != "x-default")
						{
							CultureInfo cultureInfo;
							try
							{
								cultureInfo = CultureInfo.GetCultureInfo(languages[i]);
							}
							catch
							{
								continue;
							}
							mlString[cultureInfo] = textValue.Value;
						}
						else
							mlString.DefaultString = textValue.Value;
					}
					else
					{
						error = true;
						break;
					}
				}
				if (!error)
					return mlString;
			}

			//轉成一般陣列
			object[] values = new object[_Items.Count];
			for (int i = 0; i < values.Length; ++i)
			{
				XmpPropertyValue element = _Items[i];
				values[i] = (element != null ? element.ExtractValue() : null);
			}
			return values;
		}
		#endregion
		#region IsLanguageAlternative
		/// <summary>
		/// 確認此陣列是否為 Language Alternative。
		/// </summary>
		/// <param name="languages">接收 Language Alternative 中語言清單的 List，預設值為 Null (Visual Basic 為 Nothing)。</param>
		/// <returns>True 表示此陣列為 Language Alternative，False 表示不是。</returns>
		public bool IsLanguageAlternative(List<string> languages = null)
		{
			if (_ArrayType == XmpArrayType.Alternative)
			{
				//清除集合
				if (languages != null)
					languages.Clear();

				//搜尋 xml:lang Qualifier
				for (int i = 0; i < _Items.Count; ++i)
				{
					XmpPropertyValue element = _Items[i];
					if (element == null)
						return false;
					for (int j = 0; j < element.Qualifiers.Count; ++j)
					{
						XmpPropertyQualifier qualifier = element.Qualifiers[j];
						bool langFound = false;
						if (qualifier.Name == "xml:lang")
						{
							if (languages != null)
								languages.Add(qualifier.Value);
							langFound = true;
							break;
						}
						if (!langFound)
							return false;
					}
				}

				//確認完成
				return true;
			}
			return false;
		}
		#endregion
		#region Items
		/// <summary>
		/// 取得陣列元素集合。
		/// </summary>
		public List<XmpPropertyValue> Items
		{
			get
			{
				return _Items;
			}
		}
		#endregion
		#region SerializeCore
		protected override void SerializeCore(XmlNode containerNode)
		{
			//寫入 rdf 節點
			string rdfNodeName;
			switch (_ArrayType)
			{
				case XmpArrayType.Unordered:
					rdfNodeName = "Bag";
					break;
				case XmpArrayType.Ordered:
					rdfNodeName = "Seq";
					break;
				case XmpArrayType.Alternative:
					rdfNodeName = "Alt";
					break;
				default:
					return;
			}
			XmlNode rdfNode = this.CreateRdfNode(containerNode, rdfNodeName);
			containerNode.AppendChild(rdfNode);

			//寫入元素
			foreach (XmpPropertyValue item in _Items)
			{
				if (item != null)
				{
					//搜尋 xml:lang Qualifier
					XmpPropertyQualifier langQualifier = null;
					for (int i = item.Qualifiers.Count - 1; i >= 0; --i)
					{
						XmpPropertyQualifier qualifier = item.Qualifiers[i];
						if (qualifier != null && qualifier.Name == "xml:lang")
						{
							langQualifier = qualifier;
							break;
						}
					}

					//建立元素節點
					XmlNode rdfLiNode = this.CreateRdfNode(rdfNode, "li");
					rdfNode.AppendChild(rdfLiNode);
					if (langQualifier != null)
					{
						XmlAttribute attr = containerNode.OwnerDocument.CreateAttribute("xml:lang");
						attr.Value = langQualifier.Value;
						rdfLiNode.Attributes.Append(attr);
					}
					item.Serialize(rdfLiNode);
				}
			}
		}
		#endregion
	}
	#endregion
	#region BooleanXmpPropertyValue
	/// <summary>
	/// 型別為 Boolean 的 XMP Property 值。
	/// </summary>
	public class BooleanXmpPropertyValue : SimpleStringXmpPropertyValue<bool>
	{ 
		#region 建構子
		/// <summary>
		/// 初始化新的 BooleanXmpPropertyValue 執行個體。
		/// </summary>
		public BooleanXmpPropertyValue()
		{ }
		/// <summary>
		/// 初始化新的 BooleanXmpPropertyValue 執行個體。
		/// </summary>
		/// <param name="value">布林值。</param>
		public BooleanXmpPropertyValue(bool value)
			: base(value)
		{ }
		#endregion
		#region CloneCore
		/// <summary>
		/// 建立副本。
		/// </summary>
		/// <returns>BooleanXmpPropertyValue 副本。</returns>
		protected override XmpPropertyValue CloneCore()
		{
			return new BooleanXmpPropertyValue(this.Value);
		}
		#endregion
	}
	#endregion
	#region DateXmpPropertyValue
	/// <summary>
	/// 型別為 Date 的 XMP Property 值。
	/// </summary>
	public class DateXmpPropertyValue : SimpleStringXmpPropertyValue<DateTime>
	{
		#region 建構子
		/// <summary>
		/// 初始化新的 DateXmpPropertyValue 執行個體。
		/// </summary>
		public DateXmpPropertyValue()
		{ }
		/// <summary>
		/// 初始化新的 DateXmpPropertyValue 執行個體。
		/// </summary>
		/// <param name="value">日期時間。</param>
		public DateXmpPropertyValue(DateTime value)
			: base(value)
		{ }
		#endregion
		#region CloneCore
		/// <summary>
		/// 建立副本。
		/// </summary>
		/// <returns>DateXmpPropertyValue 副本。</returns>
		protected override XmpPropertyValue CloneCore()
		{
			return new DateXmpPropertyValue(this.Value);
		}
		#endregion
		#region SerializeToString
		protected override string SerializeToString(DateTime value)
		{
			return this.Value.ToString("yyyy-MM-ddThh:mm:ss.sTZD");
		}
		#endregion
	}
	#endregion
	#region IntegerXmpPropertyValue
	/// <summary>
	/// 型別為 Integer 的 XMP Property 值。
	/// </summary>
	public class IntegerXmpPropertyValue : SimpleStringXmpPropertyValue<long>
	{
		#region 建構子
		/// <summary>
		/// 初始化新的 IntegerXmpPropertyValue 執行個體。
		/// </summary>
		public IntegerXmpPropertyValue()
		{ }
		/// <summary>
		/// 初始化新的 IntegerXmpPropertyValue 執行個體。
		/// </summary>
		/// <param name="value">整數值。</param>
		public IntegerXmpPropertyValue(long value)
			: base(value)
		{ }
		#endregion
		#region CloneCore
		/// <summary>
		/// 建立副本。
		/// </summary>
		/// <returns>IntegerXmpPropertyValue 副本。</returns>
		protected override XmpPropertyValue CloneCore()
		{
			return new IntegerXmpPropertyValue(this.Value);
		}
		#endregion
	}
	#endregion
	#region RationalXmpPropertyValue
	/// <summary>
	/// 型別為 Rational 的 XMP Property 值。
	/// </summary>
	public class RationalXmpPropertyValue : SimpleStringXmpPropertyValue<Rational>
	{
		#region 建構子
		/// <summary>
		/// 初始化新的 RationalXmpPropertyValue 執行個體。
		/// </summary>
		public RationalXmpPropertyValue()
		{ }
		/// <summary>
		/// 初始化新的 RationalXmpPropertyValue 執行個體。
		/// </summary>
		/// <param name="value">分數值。</param>
		public RationalXmpPropertyValue(Rational value)
			: base(value)
		{ }
		#endregion
		#region CloneCore
		/// <summary>
		/// 建立副本。
		/// </summary>
		/// <returns>RationalXmpPropertyValue 副本。</returns>
		protected override XmpPropertyValue CloneCore()
		{
			return new RationalXmpPropertyValue(this.Value);
		}
		#endregion
	}
	#endregion
	#region RealXmpPropertyValue
	/// <summary>
	/// 型別為 Real 的 XMP Property 值。
	/// </summary>
	public class RealXmpPropertyValue : SimpleStringXmpPropertyValue<double>
	{
		#region 建構子
		/// <summary>
		/// 初始化新的 RealXmpPropertyValue 執行個體。
		/// </summary>
		public RealXmpPropertyValue()
		{ }
		/// <summary>
		/// 初始化新的 RealXmpPropertyValue 執行個體。
		/// </summary>
		/// <param name="value">浮點數值。</param>
		public RealXmpPropertyValue(double value)
			: base(value)
		{ }
		#endregion
		#region CloneCore
		/// <summary>
		/// 建立副本。
		/// </summary>
		/// <returns>RealXmpPropertyValue 副本。</returns>
		protected override XmpPropertyValue CloneCore()
		{
			return new RealXmpPropertyValue(this.Value);
		}
		#endregion
	}
	#endregion
	#region SimpleStringXmpPropertyValue
	/// <summary>
	/// 具有單一值，以字串儲存的 XMP Property 值。
	/// </summary>
	public abstract class SimpleStringXmpPropertyValue<T> : SimpleXmpPropertyValue<T>
	{
		#region 建構子
		/// <summary>
		/// 初始化新的 SimpleStringXmpPropertyValue 執行個體。
		/// </summary>
		protected SimpleStringXmpPropertyValue()
		{ }
		/// <summary>
		/// 初始化新的 SimpleStringXmpPropertyValue 執行個體。
		/// </summary>
		/// <param name="value">XMP Property 值。</param>
		protected SimpleStringXmpPropertyValue(T value)
			: base(value)
		{ }
		#endregion
		#region SerializeCore
		protected override void SerializeCore(XmlNode containerNode)
		{
			//轉成字串
			string str = this.SerializeToString(this.Value);

			//加入文字節點
			if (str != null)
			{
				XmlText textNode = containerNode.OwnerDocument.CreateTextNode(str);
				containerNode.AppendChild(textNode);
			}
		}
		#endregion
		#region SerializeToString
		/// <summary>
		/// 將指定的值轉成對應的字串。
		/// </summary>
		/// <param name="value">指定的值。</param>
		/// <returns>對應的字串。</returns>
		protected virtual string SerializeToString(T value)
		{
			return value.ToString();
		}
		#endregion
	}
	#endregion
	#region SimpleXmpPropertyValue
	/// <summary>
	/// 具有單一值的 XMP Property 值。
	/// </summary>
	public abstract class SimpleXmpPropertyValue : XmpPropertyValue
	{
		#region 欄位
		object _Value;
		#endregion
		#region 建構子
		internal SimpleXmpPropertyValue()
		{ }
		internal SimpleXmpPropertyValue(object value)
		{
			_Value = value;
		}
		#endregion
		#region ExtractValue
		/// <summary>
		/// 取得此 XMP Property 值所代表的實際內容。
		/// </summary>
		/// <returns>XMP Property 值所代表的實際內容。</returns>
		public override object ExtractValue()
		{
			return _Value;
		}
		#endregion
		#region GetValue
		internal object GetValue()
		{
			return _Value;
		}
		#endregion
		#region SetValue
		internal void SetValue(object value)
		{
			_Value = value;
		}
		#endregion
	}
	/// <summary>
	/// 具有單一值的 XMP Property 值。
	/// </summary>
	public abstract class SimpleXmpPropertyValue<T> : SimpleXmpPropertyValue
	{
		#region 建構子
		/// <summary>
		/// 初始化新的 SimpleXmpPropertyValue 執行個體。
		/// </summary>
		protected SimpleXmpPropertyValue()
		{ }
		/// <summary>
		/// 初始化新的 SimpleXmpPropertyValue 執行個體。
		/// </summary>
		/// <param name="value">XMP Property 值。</param>
		protected SimpleXmpPropertyValue(T value)
			: base(value)
		{ }
		#endregion
		#region Value
		/// <summary>
		/// 取得或設定 XMP Property 值。
		/// </summary>
		public T Value
		{
			get
			{
				return (T)this.GetValue();
			}
			set
			{
				this.SetValue(value);
			}
		}
		#endregion
	}
	#endregion
	#region StructureXmpPropertyValue
	/// <summary>
	/// 結構型別的 XMP Property 值。
	/// </summary>
	public abstract class StructureXmpPropertyValue : XmpPropertyValue
	{
		#region 欄位
		XmpSchema _Schema;
		#endregion
		#region 建構子
		/// <summary>
		/// 初始化新的 StructureXmpPropertyValue 執行個體。
		/// </summary>
		/// <param name="schema">結構欄位的 XMP Schema。</param>
		protected StructureXmpPropertyValue(XmpSchema schema)
		{
			_Schema = schema;
		}
		#endregion
		#region CopyFieldsTo
		/// <summary>
		/// 將所有欄位值複製至指定的 StructureXmpPropertyValue 物件中。
		/// </summary>
		/// <param name="value">指定的 StructureXmpPropertyValue 物件。</param>
		/// <exception cref="ArgumentException">欄位複製錯誤。</exception>
		/// <exception cref="ArgumentNullException">value 為 Null (Visual Basic 為 Nothing)。</exception>
		public void CopyFieldsTo(StructureXmpPropertyValue value)
		{
			//確認參數
			if (value == null)
				throw new ArgumentNullException("value");
			if (value == this)
				return;

			//複製欄位
			string[] fieldNames = this.FieldNames;
			if (fieldNames != null)
			{
				for (int i = fieldNames.Length - 1; i >= 0; --i)
				{
					string fieldName = fieldNames[i];
					if (fieldName != null)
						value.SetFieldCore(fieldName, this.GetFieldCore(fieldName));
				}
			}
		}
		#endregion
		#region FieldNames
		/// <summary>
		/// 取得所有的欄位名稱。
		/// </summary>
		public abstract string[] FieldNames { get; }
		#endregion
		#region GetField
		/// <summary>
		/// 取得指定名稱的欄位值。
		/// </summary>
		/// <param name="name">欄位名稱。</param>
		/// <returns>指定名稱的欄位值。</returns>
		/// <exception cref="ArgumentException">指定的欄位不存在。</exception>
		/// <exception cref="ArgumentNullException">name 為 Null (Visual Basic 為 Nothing)。</exception>
		public XmpPropertyValue GetField(string name)
		{
			//確認參數
			if (name == null)
				throw new ArgumentNullException("name");

			//取得欄位值
			return this.GetFieldCore(name);
		}
		#endregion
		#region GetFieldCore
		/// <summary>
		/// 取得指定名稱的欄位值。
		/// </summary>
		/// <param name="name">欄位名稱。</param>
		/// <returns>指定名稱的欄位值。</returns>
		/// <exception cref="ArgumentException">指定的欄位不存在。</exception>
		protected abstract XmpPropertyValue GetFieldCore(string name);
		#endregion
		#region Schema
		/// <summary>
		/// 取得結構欄位的 XMP Schema。
		/// </summary>
		public XmpSchema Schema
		{
			get
			{
				return _Schema;
			}
		}
		#endregion
		#region SerializeCore
		protected override void SerializeCore(XmlNode containerNode)
		{
			//取得所有欄位名稱
			string[] fieldNames = this.FieldNames;

			//建立 rdf:Description 節點
			XmpSchema schema = _Schema;
			XmlNode rdfNode = this.CreateRdfNode(containerNode, "Description");
			if (schema != null)
			{
				XmlAttribute attr = rdfNode.OwnerDocument.CreateAttribute("xmlns:" + schema.NamespacePrefix);
				attr.Value = schema.NamespaceURI;
				rdfNode.Attributes.Append(attr);
			}
			containerNode.AppendChild(rdfNode);

			//建立欄位節點
			for (int i = 0; i < fieldNames.Length; ++i)
			{
				//取得欄位名稱
				string fieldName = fieldNames[i];
				if (string.IsNullOrEmpty(fieldName))
					continue;

				//取得欄位值
				XmpPropertyValue value = this.GetFieldCore(fieldName);
				if (value == null)
					continue;

				//建立欄位節點
				XmlNode fieldNode;
				if (schema != null)
					fieldNode = rdfNode.OwnerDocument.CreateElement(schema.NamespacePrefix, fieldName, schema.NamespaceURI);
				else
					fieldNode = rdfNode.OwnerDocument.CreateElement(fieldName);
				rdfNode.AppendChild(fieldNode);

				//建立值節點
				value.Serialize(fieldNode);
			}
		}
		#endregion
		#region SetField
		/// <summary>
		/// 設定指定名稱的欄位值。
		/// </summary>
		/// <param name="name">指定的欄位名稱。</param>
		/// <param name="value">欄位值。</param>
		/// <exception cref="ArgumentException">欄位不存在 -或- 無效的欄位值。</exception>
		/// <exception cref="ArgumentNullException">name 為 Null (Visual Basic 為 Nothing)。</exception>
		public void SetField(string name, XmpPropertyValue value)
		{
			//確認參數
			if (name == null)
				throw new ArgumentNullException("name");

			//設定欄位
			this.SetFieldCore(name, value);
		}
		#endregion
		#region SetFieldCore
		/// <summary>
		/// 設定指定名稱的欄位值。
		/// </summary>
		/// <param name="name">指定的欄位名稱。</param>
		/// <param name="value">欄位值。</param>
		/// <exception cref="ArgumentException">欄位不存在 -或- 無效的欄位值。</exception>
		protected abstract void SetFieldCore(string name, XmpPropertyValue value);
		#endregion
	}
	#endregion
	#region TextXmpPropertyValue
	/// <summary>
	/// 型別為 Text 的 XMP Property 值。
	/// </summary>
	public class TextXmpPropertyValue : SimpleStringXmpPropertyValue<string>
	{
		#region 建構子
		/// <summary>
		/// 初始化新的 TextXmpPropertyValue 執行個體。
		/// </summary>
		public TextXmpPropertyValue()
		{ }
		/// <summary>
		/// 初始化新的 TextXmpPropertyValue 執行個體。
		/// </summary>
		/// <param name="value">字串。</param>
		public TextXmpPropertyValue(string value)
			: base(value)
		{ }
		#endregion
		#region CloneCore
		/// <summary>
		/// 建立副本。
		/// </summary>
		/// <returns>TextXmpPropertyValue 副本。</returns>
		protected override XmpPropertyValue CloneCore()
		{
			return new TextXmpPropertyValue(this.Value);
		}
		#endregion
	}
	#endregion
	#region UnknownXmpPropertyValue
	/// <summary>
	/// 表示未知格式的 XMP Property 值。
	/// </summary>
	public class UnknownXmpPropertyValue : SimpleXmpPropertyValue<XmlNode>
	{
		#region 建構子
		/// <summary>
		/// 初始化新的 UnknownXmpPropertyValue 執行個體。
		/// </summary>
		/// <param name="node">表示值的原始 XML 節點。</param>
		public UnknownXmpPropertyValue(XmlNode node)
			: base(node)
		{ }
		#endregion
		#region CloneCore
		/// <summary>
		/// 建立副本。
		/// </summary>
		/// <returns>UnknownXmpPropertyValue 副本。</returns>
		protected override XmpPropertyValue CloneCore()
		{
			return new UnknownXmpPropertyValue(this.Value);
		}
		#endregion
		#region SerializeCore
		protected override void SerializeCore(XmlNode containerNode)
		{
			//取得值的根節點
			XmlNode rootNode = this.Value;
			if (rootNode == null)
				return;

			//建立值節點
			containerNode.AppendChild(rootNode.CloneNode(true));
		}
		/*
		void SerializeCore(XmlWriter writer, XmlNode node, bool isRootNode)
		{
			//寫入字串
			if (node is XmlText)
			{
				writer.WriteString(node.Value);
				return;
			}

			//收集子節點的 Namespace URI
			Dictionary<string, string> namespaces = new Dictionary<string, string>();
			XmlNode childNode = node.FirstChild;
			while (childNode != null)
			{
				if (!string.IsNullOrEmpty(childNode.Prefix) && !namespaces.ContainsKey(childNode.Prefix))
					namespaces[childNode.Prefix] = childNode.NamespaceURI;
				childNode = childNode.NextSibling;
			}
			if (isRootNode && !string.IsNullOrEmpty(node.Prefix) && !namespaces.ContainsKey(node.Prefix))
				namespaces[node.Prefix] = node.NamespaceURI;

			//寫入根節點
			writer.WriteStartElement(node.Name);
			foreach (XmlAttribute attr in node.Attributes)
			{
				if (attr.Name.IndexOf("xmlns:") != 0)
					writer.WriteAttributeString(attr.LocalName, attr.Prefix, attr.Value);
			}

			//寫入 Namespace URI
			foreach (KeyValuePair<string, string> pair in namespaces)
				writer.WriteAttributeString(pair.Key, "xmlns", pair.Value);

			//寫入子節點
			childNode = node.FirstChild;
			while (childNode != null)
			{
				this.SerializeCore(writer, childNode, false);
				childNode = childNode.NextSibling;
			}

			//寫入結束節點
			writer.WriteEndElement();
		}
		*/
		#endregion
	}
	#endregion
	#region XmpArrayType
	/// <summary>
	/// XMP 陣列類型。
	/// </summary>
	public enum XmpArrayType
	{
		/// <summary>
		/// 未排序陣列。
		/// </summary>
		Unordered,
		/// <summary>
		/// 已排序陣列。
		/// </summary>
		Ordered,
		/// <summary>
		/// 多選一陣列。
		/// </summary>
		Alternative,
	}
	#endregion
	#region XmpPropertyValue
	/// <summary>
	/// XMP Property 值基底類別。
	/// </summary>
	public abstract class XmpPropertyValue : ICloneable
	{
		#region 欄位
		static List<IXmpPropertyValueFactory> _Factories = new List<IXmpPropertyValueFactory>();
		List<XmpPropertyQualifier> _Qualifiers = new List<XmpPropertyQualifier>();
		static TextXmpPropertyValueFactory _TextFactory = new TextXmpPropertyValueFactory();
		#endregion
		#region 型別建構子
		static XmpPropertyValue()
		{
			_Factories.AddRange(new IXmpPropertyValueFactory[]{
				new ArrayXmpPropertyValueFactory(),
				new BooleanXmpPropertyValueFactory(),
				new DateXmpPropertyValueFactory(),
				new FlashXmpPropertyValueFactory(),
				new IntegerXmpPropertyValueFactory(),
				new RationalXmpPropertyValueFactory(),
				new RealXmpPropertyValueFactory(),
				new MicrosoftPhoto.RegionXmpPropertyValueFactory(),
				new MicrosoftPhoto.RegionInfoXmpPropertyValueFactory(),
			});
		}
		#endregion
		#region 建構子
		/// <summary>
		/// 初始化新的 XmpPropertyValue 執行個體。
		/// </summary>
		protected XmpPropertyValue()
		{ }
		#endregion
		#region AddFactory
		/// <summary>
		/// 加入新的 IXmpPropertyValueFactory 介面。
		/// </summary>
		/// <param name="factory">IXmpPropertyValueFactory 介面。</param>
		/// <exception cref="ArgumentNullException">factory 為 Null (Visual Basic 為 Nothing)。</exception>
		public static void AddFactory(IXmpPropertyValueFactory factory)
		{
			if (factory == null)
				throw new ArgumentNullException("factory");
			lock (_Factories)
			{
				_Factories.Add(factory);
			}
		}
		#endregion
		#region Clone
		/// <summary>
		/// 建立副本。
		/// </summary>
		/// <returns>XmpPropertyValue 副本。</returns>
		public XmpPropertyValue Clone()
		{
			//建立副本
			XmpPropertyValue value = this.CloneCore();

			//複製資料
			for (int i = 0, count = _Qualifiers.Count; i < count; ++i)
				value._Qualifiers.Add(_Qualifiers[i].Clone<XmpPropertyQualifier>());

			//回傳
			return value;
		}
		#endregion
		#region CloneCore
		/// <summary>
		/// 建立副本。
		/// </summary>
		/// <returns>XmpPropertyValue 副本。</returns>
		protected abstract XmpPropertyValue CloneCore();
		#endregion
		#region Create
		/// <summary>
		/// 使用表示 XMP Property 值的 XML 節點建立對應的 XmpPropertyValue。
		/// </summary>
		/// <param name="valueNode">表示 XMP Property 值的 XML 節點。</param>
		/// <returns>對應的 XmpPropertyValue。</returns>
		/// <exception cref="ArgumentNullException">valueNode 為 Null (Visual Basic 為 Nothing)。</exception>
		public static XmpPropertyValue Create(XmlNode valueNode)
		{
			//確認
			if (valueNode == null)
				throw new ArgumentNullException("valueNode");

			//使用 Factory 建立值
			XmpPropertyValue value;
			lock (_Factories)
			{
				for (int i = 0, count = _Factories.Count; i < count; ++i)
				{
					try
					{
						if (_Factories[i].TryCreate(valueNode, out value) && value != null)
							return value;
					}
					catch
					{ }
				}
			}

			//建立 TextXmpPropertyValue
			if (_TextFactory.TryCreate(valueNode, out value))
				return value;

			//建立 UnknownXmpPropertyValue
			return new UnknownXmpPropertyValue(valueNode);
		}
		#endregion
		#region CreateRdfNode
		internal XmlNode CreateRdfNode(XmlNode parentNode, string localName)
		{
			//if (parentNode.NamespaceURI != "http://www.w3.org/1999/02/22-rdf-syntax-ns#")
			return parentNode.OwnerDocument.CreateElement("rdf", localName, "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
			//return parentNode.OwnerDocument.CreateElement(parentNode.Prefix + ":" + localName);
		}
		#endregion
		#region ExtractValue
		/// <summary>
		/// 取得此 XMP Property 值所代表的實際內容。
		/// </summary>
		/// <returns>XMP Property 值所代表的實際內容。</returns>
		public virtual object ExtractValue()
		{
			return this;
		}
		#endregion
		#region ICloneable.Clone
		object ICloneable.Clone()
		{
			return this.CloneCore();
		}
		#endregion
		#region Qualifiers
		/// <summary>
		/// 取得 XMP Property Qualifier 集合。
		/// </summary>
		public List<XmpPropertyQualifier> Qualifiers
		{
			get
			{
				return _Qualifiers;
			}
		}
		#endregion
		#region RemoveFactory
		/// <summary>
		/// 移除指定的 IXmpPropertyValueFactory 介面。
		/// </summary>
		/// <param name="factory">要移除的 IXmpPropertyValueFactory 介面。</param>
		/// <exception cref="ArgumentNullException">factory 為 Null (Visual Basic 為 Nothing)。</exception>
		public static void RemoveFactory(IXmpPropertyValueFactory factory)
		{
			if (factory == null)
				throw new ArgumentNullException("factory");
			lock (_Factories)
			{
				_Factories.Remove(factory);
			}
		}
		#endregion
		#region Serialize
		/// <summary>
		/// 將值儲存為 XML 文件。
		/// </summary>
		/// <param name="containerNode">XMP 屬性值的父節點。</param>
		/// <exception cref="ArgumentNullException">containerNode 為 Null (Visual Basic 為 Nothing)。</exception>
		public void Serialize(XmlNode containerNode)
		{
			//確認
			if (containerNode == null)
				throw new ArgumentNullException("containerNode");

			//寫入 XML 文件
			if (_Qualifiers.Count == 0 || (_Qualifiers.Count == 1 && _Qualifiers[0].Name == "xml:lang"))
				this.SerializeCore(containerNode);
			else
			{
				//收集 Qualifier XMP Schema
				Dictionary<string, XmpSchema> schemas = new Dictionary<string, XmpSchema>();
				for (int i = _Qualifiers.Count - 1; i >= 0; --i)
				{
					XmpPropertyQualifier qualifier = _Qualifiers[i];
					if (qualifier != null && qualifier.Name != "xml:lang" && qualifier.Schema != null)
					{
						XmpSchema schema = qualifier.Schema;
						if (!schemas.ContainsKey(schema.NamespacePrefix))
							schemas.Add(schema.NamespacePrefix, schema);
					}
				}

				//建立 rdf:Description 節點
				XmlDocument document = containerNode.OwnerDocument;
				XmlNode rdfNode = this.CreateRdfNode(containerNode, "Description");
				foreach (XmpSchema schema in schemas.Values)
				{
					XmlAttribute attr = document.CreateAttribute("xmlns:" + schema.NamespacePrefix, schema.NamespaceURI);
					containerNode.Attributes.Append(attr);
				}
				containerNode.AppendChild(rdfNode);

				//建立 rdf:value 節點
				XmlNode rdfValueNode = this.CreateRdfNode(rdfNode, "value");
				rdfNode.AppendChild(rdfValueNode);

				//建立值節點
				this.SerializeCore(rdfValueNode);

				//建立 Qualifier 節點
				for (int i = _Qualifiers.Count - 1; i >= 0; --i)
				{
					XmpPropertyQualifier qualifier = _Qualifiers[i];
					if (qualifier != null && qualifier.Name != "xml:lang")
					{
						XmpSchema schema = qualifier.Schema;
						XmlNode qualifierNode;
						if (schema != null)
							qualifierNode = document.CreateElement(schema.NamespacePrefix + ":" + qualifier.Name);
						else
							qualifierNode = document.CreateElement(qualifier.Name);
						rdfNode.AppendChild(qualifierNode);
					}
				}
			}
		}
		#endregion
		#region SerializeCore
		/// <summary>
		/// 將值儲存為 XML 文件。
		/// </summary>
		/// <param name="containerNode">XMP 屬性值的父節點。</param>
		protected abstract void SerializeCore(XmlNode containerNode);
		#endregion
	}
	#endregion
}
